#ifndef SMBIOS_H
#define SMBIOS_H

static const char * sm_ports[] = 
{
    "None",
    "Parallel Port XT/AT Compatible",
    "Parallel Port PS/2",
    "Parallel Port ECP",
    "Parallel Port EPP",
    "Parallel Port ECP/EPP",
    "Serial Port XT/AT Compatible",
    "Serial Port 16450 Compatible",
    "Serial Port 16550 Compatible",
    "Serial Port 16550A Compatible",
    "SCSI Port",
    "MIDI Port",
    "Joy Stick Port",
    "Keyboard Port",
    "Mouse Port",
    "SSA SCSI",
    "USB",
    "FireWire (IEEE P1394)",
    "PCMCIA Type II",
    "PCMCIA Type II",
    "PCMCIA Type III",
    "Cardbus",
    "Access Bus Port",
    "SCSI II",
    "SCSI Wide",
    "PC-98",
    "PC-98-Hireso",
    "PC-H98",
    "Video Port",
    "Audio Port",
    "Modem Port",
    "Network Port",
    "SATA",
    "SAS",
    "8251 Compatible",
    "8251 FIFO Compatible"
};

static const char * sm_connectors[] = 
{
    "None",
    "Centronics",
    "Mini Centronics",
    "Proprietary",
    "DB-25 pin male",
    "DB-25 pin female",
    "DB-15 pin male",
    "DB-15 pin female",
    "DB-9 pin male",
    "DB-9 pin female",
    "RJ-11",
    "RJ-45",
    "50 Pin MiniSCSI",
    "Mini-DIN",
    "Micro-DIN",
    "PS/2",
    "Infrared",
    "HP-HIL",
    "Access Bus (USB)",
    "SSA SCSI",
    "Circular DIN-8 male",
    "Circular DIN-8 female",
    "On Board IDE",
    "On Board Floppy",
    "9 Pin Dual Inline (pin 10 cut)",
    "25 Pin Dual Inline (pin 26 cut)",
    "50 Pin Dual Inline",
    "68 Pin Dual Inline",
    "On Board Sound Input from CD-ROM",
    "Mini-Centronics Type-14",
    "Mini-Centronics Type-26",
    "Mini-jack (headphones)",
    "BNC",
    "1394",
    "SAS/SATA Plug Receptacle",
    "PC-98",
    "PC-98Hireso",
    "PC-H98",
    "PC-98Note",
    "PC-98Full"
};

static const char * sm_memory_slots[0x10] = 
{
    "UNKNOWN",
    "Other",
    "Unknown",
    "SIMM",
    "SIP",
    "Chip",
    "DIP",
    "ZIP",
    "Proprietary Card",
    "DIMM",
    "TSOP",
    "Row of chips",
    "RIMM",
    "SODIMM",
    "SRIMM",
    "FB-DIMM"
};

static const char * sm_memory_types[0x15] = 
{
    "UNKNOWN",
    "Other",
    "Unknown",
    "DRAM",
    "EDRAM",
    "VRAM",
    "SRAM",
    "RAM",
    "ROM",
    "FLASH",
    "EEPROM",
    "FEPROM",
    "EPROM",
    "CDRAM",
    "3DRAM",
    "SDRAM",
    "SGRAM",
    "RDRAM",
    "DDR",
    "DDR2",
    "DDR2 FB-DIMM"
};

static const char * sm_slot_types[] = 
{
    "UNKNOWN",
    "Other",
    "Unknown",
    "ISA",
    "MCA",
    "EISA",
    "PCI",
    "PC Card (PCMCIA)",
    "VL-VESA",
    "Proprietary",
    "Processor Card Slot",
    "Proprietary Memory Card Slot",
    "I/O Riser Card Slot",
    "NuBus",
    "PCI - 66MHz Capable",
    "AGP",
    "AGP 2X",
    "AGP 4X",
    "PCI-X",
    "AGP 8X",
    "PC-98/C20",
    "PC-98/C24",
    "PC-98/E",
    "PC-98/Local Bus",
    "PC-98/Card",
    "PCI Express (see below)",
    "PCI Express x1",
    "PCI Express x2",
    "PCI Express x4",
    "PCI Express x8",
    "PCI Express x16"
};

/* 17 */
struct sm_memdev_s
{
    uint16_t memory_handle;
    uint16_t error_handle;
    uint16_t total_width;
    uint16_t data_width;
    uint16_t size;
    uint8_t  form_factor;
    uint8_t  device_set;
    uint8_t  device_locator;
    uint8_t  bank_locator;
    uint8_t  type;
    uint16_t type_detail;
    uint16_t speed;
    uint8_t  manufacturer;
    uint8_t  serial;
    uint8_t  asset;
    uint8_t  part;
    uint8_t  attributes;
    
    char *   device_locator_s;
    char *   bank_locator_s;
    char *   manufacturer_s;
    char *   serial_s;
    char *   asset_s;
    char *   part_s;
} sm_memdev[64];

/* 9 */
struct sm_slot_s
{
    uint8_t  designation;
    uint8_t  type;
    uint8_t  data_bus_width;
    uint8_t  current_usage;
    uint8_t  slot_length;
    uint16_t id;
    uint8_t  characteristics[2];
    uint16_t segment_group_number;
    uint8_t  bus_number;
    uint8_t  device_number;
    
    char *  designation_s; 
} sm_slot[64];

/* 8 */
struct sm_port_s
{
    uint8_t  internal_reference_designator;
    uint8_t  internal_connector_type;
    uint8_t  external_reference_designator;
    uint8_t  external_connector_type;
    uint8_t  port_type;
    
    char *   internal_reference_designator_s;
    char *   external_reference_designator_s;
} sm_port[64];

/* 4 */
struct sm_cpu_s
{
    uint8_t  socket;
    uint8_t  type;
    uint8_t  family;
    uint8_t  manufacturer;
    uint32_t id;
    uint8_t  version;
    uint8_t  voltage;
    uint16_t external_clock;
    uint16_t max_speed;
    uint16_t current_speed;
    uint8_t  status;
    uint8_t  upgrade;
    uint16_t L1_cache_handle;
    uint16_t L2_cache_handle;
    uint16_t L3_cache_handle;
    uint8_t  serial;
    uint8_t  asset;
    uint8_t  part;
    uint8_t  core_count;
    uint8_t  core_enabled;
    uint8_t  thread_count;
    uint16_t characteristics;
    uint16_t ext_family;
    
    char *   socket_s;
    char *   manufacturer_s;
    char *   version_s;
    char *   serial_s;
    char *   asset_s;
    char *   part_s;
} sm_cpu[64]; /* yeah, that's right... 64 CPU's baby!!! */

/* 3 */
struct sm_chas_s
{
    uint8_t  manufacturer;
    uint8_t  type;
    uint8_t  version;
    uint8_t  serial;
    uint8_t  asset;
    uint8_t  boot_state;
    uint8_t  power_state;
    uint8_t  thermal_state;
    uint8_t  security_state;
    uint32_t oem_defined;
    uint8_t  height;
    uint8_t  power_cord_count;
    uint8_t  contained_element_count;
    uint8_t  contained_record_length;
    uint8_t  contained_elements[256][256]; /* count * length */
    
    char *   manufacturer_s;
    char *   version_s;
    char *   serial_s;
    char *   asset_s;
} sm_chas[4];

/* 2 */
struct sm_mod_s
{
    uint8_t  manufacturer;
    uint8_t  product;
    uint8_t  version;
    uint8_t  serial;
    uint8_t  asset;
    uint8_t  family;
    uint8_t  feature_flags;
    uint8_t  location;
    uint16_t chassis_handle;
    uint8_t  board_type;
    uint8_t  num_contained_objects;
    uint16_t contained_objects[256];    /* max */
    
    char *   manufacturer_s;
    char *   product_s;
    char *   version_s;
    char *   serial_s;
    char *   asset_s;
    char *   location_s;
} sm_mod[8];

/* 1 */
struct sm_sys_s
{
    uint8_t  manufacturer;
    uint8_t  product;
    uint8_t  version;
    uint8_t  serial;
    uint8_t  uuid[16];
    uint8_t  wakeup_type;
    uint8_t  sku;
    uint8_t  family;
    
    char *   manufacturer_s;
    char *   product_s;
    char *   version_s;
    char *   serial_s;
    char *   sku_s;
    char *   family_s;
} sm_sys[4];

/* 0 */
struct sm_bios_s
{
    uint8_t  vendor;
    uint8_t  version;
    uint16_t starting_address_segment;
    uint8_t  release_date;
    uint8_t  rom_size;
    uint8_t  characteristics[8];
    uint8_t  extension[2];
    uint8_t  major_release;
    uint8_t  minor_release;
    uint8_t  firmware_major_release;
    uint8_t  firmware_minor_release;
    
    char *   vendor_s;
    char *   version_s;
    char *   release_date_s;
} sm_bios;

struct sm_hdr_s
{
    uint8_t  type;
    uint8_t  length;
    uint16_t handle;
} sm_hdr;

struct sm_entry_s  
{
    uint8_t  anchor_string[4];
    uint8_t  checksum;
    uint8_t  length;
    uint8_t  major_version;
    uint8_t  minor_version;
    uint16_t max_struct_size;
    uint8_t  revision;
    uint8_t  formatted_area[5];
    uint8_t  interm_anchor_string[5];
    uint8_t  interm_checksum;
    uint16_t struct_table_length;
    uint32_t struct_table_address;
    uint16_t num_smbios_structures;
    uint8_t  bcd_revision;
} sm_eps;

struct sm_structures_s
{
    uint8_t  type;
    uint32_t address;
} sm_structures[64];

uint8_t sm_bios_count,
        sm_sys_count,
        sm_mod_count,
        sm_chas_count,
        sm_cpu_count,
        sm_port_count,
        sm_slot_count,
        sm_memdev_count,
        sm_structure_count;

bool smbios_present;        
bool smbios_parsing_completed;

uint8_t sm_bsp_id;
uint8_t sm_socket_count;
uint8_t sm_memdev_filled;

void parse_smbios(void);
uint32_t get_smbios_memory_count(void);

#endif



